/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package com.jeff.springWebTestNG.concurrent;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.BrokenBarrierException;
import java.util.concurrent.CyclicBarrier;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * This class is to emulate Barrier
 * 
 * @author zhou.zhefu
 */
public class BarrierEmulator {
    private static final int N_BARRIER_GATE = 3;
    private static final long timeOnStart = System.nanoTime();
    private CyclicBarrier barrier = new CyclicBarrier(N_BARRIER_GATE, new Runnable() {

        @Override
        public void run() {
            //TODO flush the result
            System.out.println("Flushing happened at Time: " + (System.nanoTime() - timeOnStart));
        }
        
    });
    
    public void start() {
        final int threadCount = 3 * N_BARRIER_GATE;
        List<Thread> workingThreads = new ArrayList<Thread>(threadCount);
        for (int i = 1; i <= threadCount; i++) {
            Thread t = new Thread(new Worker(i));
            workingThreads.add(t);
            t.start();
        }
        
        try {
            for (Thread t : workingThreads) {
                t.join();
            }
        } catch (InterruptedException ex) {
            Logger.getLogger(BarrierEmulator.class.getName()).log(Level.SEVERE, null, ex);
        }
        
        System.out.println("All works DONE!");
    }
    
    private class Worker implements Runnable {
        int id;

        public Worker(int id) {
            this.id = id;
        }

        @Override
        public void run() {
            try {
                //TODO do worker's job
                Thread.sleep(1);
                System.out.println("Worker[" + id + "] finish job at Time: " + (System.nanoTime() - timeOnStart));
                barrier.await();
            } catch (InterruptedException ex) {
                Logger.getLogger(Worker.class.getName()).log(Level.WARNING, null, ex);
            } catch (BrokenBarrierException ex) {
                Logger.getLogger(Worker.class.getName()).log(Level.WARNING, null, ex);
            }
        }
        
    }
}
